import ply.lex as lex
import re
from Import.py import *
'''
D			[0-9]
L			[a-zA-Z_]
H			[a-fA-F0-9]
E			[Ee][+-]?{D}+
FS			(f|F|l|L)
IS			(u|U|l|L)*


%{
#include <stdio.h>
#include "y.tab.h"
#include "system.h"
int linenumber=1;
void count();
char temp[100];
extern char *printcode;
%}
'''
linenumber=1
temp = ""
global printcode

reserved_words = {
      'auto' : 'AUTO',
      'break': 'BREAK',
      'case':'CASE',
      'char' : 'CHAR',
      'const':'CONST',
      'continue':'CONTINUE',
      'default':'DEFAULT',
      'do' : 'DO',
      'double' : 'DOUBLE',
      'else':'ELSE',
      'enum':'ENUM',
      'extern':'EXTERN',
      'float':'FLOAT',
      'for':'FOR',
      'goto' : 'GOTO',
      'if':'IF',
      'int':'INT',
      'long':'LONG',
      'register' : 'REGISTER',
      'return' : 'RETURN',
      'short':'SHORT',
      'signed':'SIGNED',
      'sizeof':'SIZEOF'
      'static':'STATIC',
      'struct' : 'STRUCT',
      'switch' : 'SWITCH',
      'typedef':'TYPEDEF',
      'union':'UNION',
      'unsigned':'UNSIGNED',
      'void':'VOID',
      'volatile':'VOLATILE',
      'while':'WHILE'
}      

literals=['[',']','(',')','{','}','=','>','<','!','~',':','+','-','*','/','&','|','^','%','.',';',',','?','#']

t_ELLIPSIS = '...'
t_RIGHT_ASSIGN='>>=='
t_LEFT_ASSIGN='<<=='
t_ADD_ASSIGN='\+='
t_SUB_ASSIGN='\-='
t_MUL_ASSIGN='\*='
t_DIV_ASSIGN='/='
t_AND_ASSIGN='&='
t_XOR_ASSIGN='^='
t_OR_ASSIGN='\|='
t_RIGHT_OP='>>'
t_LEFT_OP='<<'
t_INC_OP='\+\+'
t_DEC_OP='\-\-'
t_PTR_OP='\->'
t_AND_OP='&&'
t_OR_OP='\|\|'
t_LE_OP='<='
t_GE_OP='>='
t_EQ_OP='=='
t_NE_OP='!='


#[ \t\r\v\a\f]+		{ count();}		/* Ignore escape character */
#"auto"			{ count(); return(AUTO); }
#"break"			{ count(); return(BREAK); }
#"case"			{ count(); return(CASE); }
#"char"			{ count(); return(CHAR); }
#"const"			{ count(); return(CONST); }
#"continue"		{ count(); return(CONTINUE); }
#"default"		{ count(); return(DEFAULT); }
#"do"			{ count(); return(DO); }
#"double"		{ count(); return(DOUBLE); }
#"else"			{ count(); return(ELSE); }
#"enum"			{ count(); return(ENUM); }
#"extern"		{ count(); return(EXTERN); }
#"float"			{ count(); return(FLOAT); }
#"for"			{ count(); return(FOR); }
#"goto"			{ count(); return(GOTO); }
#"if"			{ count(); return(IF); }
#"int"			{ count(); return(INT); }
#"long"			{ count(); return(LONG); }
#"register"		{ count(); return(REGISTER); }
#"return"		{ count(); return(RETURN); }
#"short"			{ count(); return(SHORT); }
#"signed"		{ count(); return(SIGNED); }
#"sizeof"		{ count(); return(SIZEOF); }
#"static"		{ count(); return(STATIC); }
#"struct"		{ count(); return(STRUCT); }
#"switch"		{ count(); return(SWITCH); }
#"typedef"		{ count(); return(TYPEDEF); }
#"union"			{ count(); return(UNION); }
#"unsigned"		{ count(); return(UNSIGNED); }
#"void"			{ count(); return(VOID); }
#"volatile"		{ count(); return(VOLATILE); }
#"while"			{ count(); return(WHILE); }

def t_IDENTIFIER(t):
      r'[a-zA-Z_\$][a-zA-Z0-9_\$]*'
      t.type=reserved_map.get(t.value,"IDENTIFIER")
      if reserved_words.has_key(t.value):
	    t.type=reserved_words[t.value]
      return t	
      
'''
[a-zA-Z_\$][a-zA-Z0-9_\$]*	{ count(); 
				  yylval.string=(char *)malloc(strlen(yytext)*sizeof(char)+1);
				  strcpy(yylval.string,yytext);
				  return(IDENTIFIER);   
				}
'''
def t_LONGINTEGER(t):
	r'[1-9][0-9]*[lL]'
	return t	

def t_INTEGER(t):
	r'\d+'
	return t	

'''
[0-9][0-9]*[lL]?				{// integer and long integer
							int i=0,j=0;
//							printf("AAAAAAAAAAAA : %s \n",yytext);
							if(yytext[0] == '+' || yytext[0] == '-')
								i++;
							while(yytext[i] != '\0' && yytext[i] != 'l' && yytext[i]!= 'L'){
								temp[j] = yytext[i];
								i++;j++;
							}
							temp[j] = '\0';
							//printf(temp);		
							if(yytext[i] == '\0'){
								yylval.intValue = atoi(temp);
								if(yytext[0] == '-')
									yylval.intValue*= -1;
								//printf("Integer: %d\n",yylval.intValue);
								return(INTEGER);
							}
							
							yylval.longIntValue = atoi(temp);
							if(yytext[0] == '-')
									yylval.longIntValue*= -1;
							//printf("Long Integer: %ld",yylval.longIntValue);
							return(LONGINTEGER);
						}	
'''
def t_LONGHEXADECIMAL(t):
	r'[0][xX][0-9a-fA-F]+[lL]'
	return t

def t_HEXADECIMAL(t):
	r'[0][xX][0-9a-fA-F]+'
	return t	

'''
[0][xX][0-9a-fA-F]+[lL]? 	{// hexadecimal integer and hexa long integer
							int i=2,value=0;
							while(yytext[i] != '\0' && yytext[i] != 'l' && yytext[i]!= 'L'){
								if(yytext[i]>='0' && yytext[i] <='9')
										value=value*16+yytext[i]-'0';
								else if (yytext[i]>='a' && yytext[i]<='f')
									value= value*16+yytext[i]-'a'+10;
								else if (yytext[i]>='A' && yytext[i]<='F')
									value= value*16+yytext[i]-'F'+10;
							}
							yylval.longIntValue = yylval.intValue = value;
							if(yytext[i] == '\0'){
								//printf("Octal: %d\n",yylval.intValue);
								return(HEXADECIMAL);
							}
							//printf("Long Octal: %ld\n",yylval.longIntValue);
							return(LONGHEXADECIMAL);
						} 		
'''
def t_DECIMALDOUBLE(t):
	#r'(([0-9]+\.[0-9]+)([eE][-+]?[0-9]+)?[dD]?) | (([0-9]+\.[0-9]+)([eE][-+]?[0-9]+)?[dD]?)'
	r'(([0-9]+\.[0-9]*)([eE][-+]?[0-9]+)?[dD]?) | (([0-9]*\.[0-9]+)([eE][-+]?[0-9]+)?[dD]?)'
	return t

'''
([0-9]+\.[0-9]*)([eE][-+]?[0-9]+)?[dD]? |
([0-9]*\.[0-9]+)([eE][-+]?[0-9]+)?[dD]?		{// decimal double point literals
							int i=0,j=0;
							while(yytext[i] != '\0' && yytext[i] != 'd' && yytext[i]!= 'D'){
								temp[j] = yytext[i];
								i++;j++;
							}
							temp[j] = '\0';
							yylval.doubleValue = atof(temp);
							//printf("Decimal Double: %f\n",yylval.doubleValue);
							return(DECIMALDOUBLE);
						}
'''

def t_DECIMALDOUBLE(t):
      r'(([0-9]+\.[0-9]*)([eE][-+]?[0-9]+)?[fF]?) | (([0-9]*\.[0-9]+)([eE][-+]?[0-9]+)?[fF]?)'
      return t

'''
([0-9]+\.[0-9]*)([eE][-+]?[0-9]+)?[fF]? |
([0-9]*\.[0-9]+)([eE][-+]?[0-9]+)?[fF]?	{// decimal floating point literals
							int i=0,j=0;
							if(yytext[0] == '+' || yytext[0] == '-')
								i++;
							while(yytext[i] != '\0' && yytext[i] != 'f' && yytext[i]!= 'F'){
								temp[j] = yytext[i];
								i++;j++;
							}
							temp[j] = '\0';
							yylval.floatValue = atof(temp);
							if(yytext[0] == '-')
									yylval.floatValue*= -1;
							//printf("Float: %f\n", yylval.floatValue);
							return(DECIMALFLOAT);
						}
'''

def t_DOUBLEVAL(t):
      r'([0-9]+([eE][-+]?[0-9]+)?[dD]) | ([0-9]+([eE][-+]?[0-9]+)[dD]?)'
      return t

'''      
[0-9]+([eE][-+]?[0-9]+)?[dD] |
[0-9]+([eE][-+]?[0-9]+)[dD]?		{// double point literals 
							int i=0,j=0;
							if(yytext[0] == '+' || yytext[0] == '-')
								i++;
							while(yytext[i] != '\0' && yytext[i] != 'd' && yytext[i]!= 'D'){
								temp[j] = yytext[i];
								i++;j++;
							}
							temp[j] = '\0';
							yylval.doubleValue = atof(temp);
							if(yytext[0] == '-')
									yylval.doubleValue*= -1;
							//printf("Double Literal: %f\n", yylval.doubleValue);
							return(DOUBLEVAL);
						}
'''

def t_FLOATVAL(t):
      r'[0-9]+([eE][-+]?[0-9]+)?[fF]'
      return t

'''      
[0-9]+([eE][-+]?[0-9]+)?[fF]		{// floating point literals 
							int i=0,j=0;
							if(yytext[0] == '+' || yytext[0] == '-')
								i++;
							while(yytext[i] != '\0' && yytext[i] != 'f' && yytext[i]!= 'F'){
								temp[j] = yytext[i];
								i++;j++;
							}
							temp[j] = '\0';
							yylval.floatValue = atof(temp);
							if(yytext[0] == '-')
									yylval.floatValue*= -1;
							//printf("Floating Point: %f\n", yylval.floatValue);
							return(FLOATVAL);
						}
'''

def t_CHARACTER(t):
	r'[\'][^\\\'\"\n][\']'
	return t	

'''
[\'][^\\\'\"\n][\']				{// for handling normal character literals 
								yylval.charValue = yytext[1];
								//printf("Char: %c\n", yylval.charValue);
								return(CHARACTER);
						}
'''

def t_ESCAPECHAR(t):
	r'[\'][\\][nbtfrva\'\"\\?0][\']'
	return t	
'''
[\'][\\][nbtfrva\'\"\\\?0][\'] {// for handling std-esc character literals
								switch(yytext[2]){
									case 'n': yylval.charValue = '\n';
									case 'b': yylval.charValue = '\b';
									case 't': yylval.charValue = '\t';
									case 'f': yylval.charValue = '\f';
									case 'r': yylval.charValue = '\r';
									case 'v': yylval.charValue = '\v';
									case 'a': yylval.charValue = '\a';
									case '\'': yylval.charValue = '\'';
									case '\"': yylval.charValue = '\"';
									case '\\': yylval.charValue = '\\';
									case '?': yylval.charValue = '\?';
									case '0': yylval.charValue = '\0';
								}
								//printf("Escape char: \\%c\n", yylval.charValue);
								return(ESCAPECHAR);
						}
'''

def t_HEXLITERAL(t):
	r'[\'][\\][x][0-9a-fA-F]{1,3}[\']'
	return t	



'''
[\'][\\][x][0-9a-fA-F]{1,3}[\'] 		{// hexadecimal charater literals
							*yytext++;	//skip first inverted comma
							//copy len-1 to string. Skips last inverted comma.
							yylval.string = (char *)malloc(strlen(yytext)*sizeof(char));
							strncpy(yylval.string, yytext, strlen(yytext)-1);
							yylval.string[strlen(yytext)-1]='\0';
							//printf("Hex Char Literal %s\n",yylval.string);
							return(HEXLITERAL);
						}
'''

def t_STRING(t):
#	r'[<\"]([^\n\"\\]|([\\][nbtfrva\'\"\\\?0]))*[\">]'
	r'"[^\n]*?(?<!\\)"'
	return t
	

def t_newline(t):
    r'\n+'
    global linenumber
    linenumber = linenumber + 1
    t.lexer.lineno += t.value.count("\n")      
#[\n]			{ linenumber++; }

t_ignore = " \t\r\v\a\f"


'''
[<\"]([^\n\"\\]|([\\][nbtfrva\'\"\\\?0]))*[\">]	{	// normal string
							*yytext++;	//skip first inverted comma
							//copy len-1 to string. Skips last inverted comma.
							yylval.string = (char *)malloc(strlen(yytext)*sizeof(char));
							strncpy(yylval.string, yytext, strlen(yytext)-1);
							yylval.string[strlen(yytext)-1]='\0';
							//printf("String: %s\n", yylval.string);
							return(STRING);
						}	
'''

'''
#"..."			{ count(); return(ELLIPSIS); }
">>="			{ count(); return(RIGHT_ASSIGN); }
"<<="			{ count(); return(LEFT_ASSIGN); }
"+="			{ count(); return(ADD_ASSIGN); }
"-="			{ count(); return(SUB_ASSIGN); }
"*="			{ count(); return(MUL_ASSIGN); }
"/="			{ count(); return(DIV_ASSIGN); }
"%="			{ count(); return(MOD_ASSIGN); }
"&="			{ count(); return(AND_ASSIGN); }
"^="			{ count(); return(XOR_ASSIGN); }
"|="			{ count(); return(OR_ASSIGN); }
">>"			{ count(); return(RIGHT_OP); }
"<<"			{ count(); return(LEFT_OP); }
"++"			{ count(); return(INC_OP); }
"--"			{ count(); return(DEC_OP); }
"->"			{ count(); return(PTR_OP); }
"&&"			{ count(); return(AND_OP); }
"||"			{ count(); return(OR_OP); }
"<="			{ count(); return(LE_OP); }
">="			{ count(); return(GE_OP); }
"=="			{ count(); return(EQ_OP); }
"!="			{ count(); return(NE_OP); }

";"			{ count(); return(';'); }
("{"|"<%")		{ count(); return('{'); }
("}"|"%>")		{ count(); return('}'); }
","			{ count(); return(','); }
":"			{ count(); return(':'); }
"="			{ count(); return('='); }
"("			{ count(); return('('); }
")"			{ count(); return(')'); }
("["|"<:")		{ count(); return('['); }
("]"|":>")		{ count(); return(']'); }
"."			{ count(); return('.'); }
"&"			{ count(); return('&'); }
"!"			{ count(); return('!'); }
"~"			{ count(); return('~'); }
"-"			{ count(); return('-'); }
"+"			{ count(); return('+'); }
"*"			{ count(); return('*'); }
"/"			{ count(); return('/'); }
"%"			{ count(); return('%'); }
"<"			{ count(); return('<'); }
">"			{ count(); return('>'); }
"^"			{ count(); return('^'); }
"|"			{ count(); return('|'); }
"?"			{ count(); return('?'); }
.			{ printf("\nError : Stray %s in program on line %d\n",yytext,linenumber); }
'''

success= True
	
def t_error(t):
    global success
    print "Line %d :" % (t.lineno,) + "LEXICAL ERROR FOUND. Illegal Character: ", t.value[0] + "\n",
    t.lexer.skip(1)
    success= False

lex.lex()

'''
%%

yywrap()
{
	return(1);
}

/*
comment()
{
	char c, c1;

loop:
	while ((c = input()) != '*' && c != 0)
		putchar(c);

	if ((c1 = input()) != '/' && c != 0)
	{
		unput(c1);
		goto loop;
	}

	if (c != 0)
		putchar(c1);
}

*/
int column = 0;

void count()
{
	int i;

	for (i = 0; yytext[i] != '\0'; i++)
		if (yytext[i] == '\n')
			column = 0;
		else if (yytext[i] == '\t')
			column += 8 - (column % 8);
		else
			column++;

	//ECHO;
}


/*int check_type()
{
/*
* pseudo code --- this is what it should check
*
*	if (yytext == type_name)
*		return(TYPE_NAME);
*
*	return(IDENTIFIER);
*/

/*
*	it actually will only return IDENTIFIER
*

	return(IDENTIFIER);
}*/
'''

